/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

#pragma once

namespace Ogitors
{
    //! Billboard data class
    /*!  
        A class that keeps track of single billboard
    */
	struct BILLBOARD
	{
		Ogre::Vector3 Position;             /** Billboard position */
		Ogre::Vector3 Direction;            /** Billboard direction */
		Ogre::ColourValue Color;            /** Billboard color */
		Ogre::Radian Rotation;              /** Billboard rotation */
		Ogre::Real Width;                   /** Billboard width (not default)*/
		Ogre::Real Height;                  /** Billboard height (not default)*/
		Ogre::uint16 TexCoordIndex;         /** Billboard texture index */
		Ogre::Vector4 TexRect;              /** Billboard texture mapping rectangle */
	};

    //! Billboard editor class
    /*!  
        Billboard editor class that assists in editing billboard(s)
    */
	class OgitorExport CBillboardSetEditor: public CNodeEditor
	{
		friend class CBillboardSetEditorFactory;
	public:
		/** @copydoc CBaseEditor::getFactory() */
		static CBaseEditorFactory *getFactory();
		/** @copydoc CBaseEditor::getFactoryDynamic() */
		virtual CBaseEditorFactory *getFactoryDynamic();

        /**
        * Sets billboard type for billboard set
        * @param value billboard type (@see Ogre::BillboardType)
        * @param display flag signifying whether or not to update billboard type field in treeview
        */
		void				setBillboardType(const int& value, bool display);
        /**
        * Fetches billboard type of billboard set
        * @return billboard type of billboard set
        */
		int					getBillboardType();
        /**
        * Sets billboard sorting flag for billboard set
        * @param bSorting sorting flag for billboard set
        * @param display flag signifying whether or not to update billboard sorting field in treeview
        */
		void				setSorting(const bool& bSorting, bool display);
        /**
        * Fetches billboard sorting flag of billboard set
        * @return billboard sorting flag of billboard set
        */
		bool				getSorting();
        /**
        * Sets billboard origin for billboard set
        * @param origin billboard origin (@see Ogre::BillboardOrigin)
        * @param display flag signifying whether or not to update billboard origin field in treeview
        */
		void				setBillboardOrigin(const int& origin, bool display);
        /**
        * Fetches billboard origin of billboard set
        * @return billboard origin of billboard set
        */
		int					getBillboardOrigin();
        /**
        * Sets billboard rotation for billboard set
        * @param rotation billboard rotation (@see Ogre::BillboardRotationType)
        * @param display flag signifying whether or not to update billboard rotation field in treeview
        */
		void				setBillboardRotation(const int& rotation, bool display);
        /**
        * Fetches billboard rotation of billboard set
        * @return billboard rotation of billboard set
        */
		int					getBillboardRotation();
        /**
        * Sets billboard default width for billboard set
        * @param width billboard default width
        * @param display flag signifying whether or not to update billboard default width field in treeview
        */
		void				setWidth(const Ogre::Real& width, bool display);
        /**
        * Fetches billboard default width of billboard set
        * @return billboard default width of billboard set
        */
		Ogre::Real			getWidth();
        /**
        * Sets billboard default height for billboard set
        * @param height billboard default height
        * @param display flag signifying whether or not to update billboard default height field in treeview
        */
		void				setHeight(const Ogre::Real& height, bool display);
        /**
        * Fetches billboard default height of billboard set
        * @return billboard default height of billboard set
        */
		Ogre::Real			getHeight();
        /**
        * Sets billboard default material name for billboard set
        * @param value billboard default material name
        * @param display flag signifying whether or not to update billboard default material name field in treeview
        */
		void				setMaterial(const Ogre::String& value, bool display);
        /**
        * Fetches billboard default material name of billboard set
        * @return billboard default material name of billboard set
        */
		Ogre::String		getMaterial();
        /**
        * Sets billboard point rendering flag for billboard set
        * @param point billboard point rendering flag; if true, will render all billboards as point sprites, otherwise as normal 'quads'.
        * @param display flag signifying whether or not to update billboard point rendering flag field in treeview
        */
		void				setPointRendering(const bool& point, bool display);
        /**
        * Fetches billboard point rendering flag
        * @return billboard point rendering flag
        */
		bool				getPointRendering();
        /**
        * Sets the distance at which the object is no longer rendered for billboard set
        * @param distance distance at which the object is no longer rendered for billboard set
        * @param display flag signifying whether or not to update rendering distance field in treeview
        */
		void				setRenderingDistance(const Ogre::Real& distance, bool display);
        /**
        * Fetches the distance at which the object is no longer rendered for billboard set
        * @return the distance at which the object is no longer rendered for billboard set
        */
		Ogre::Real			getRenderingDistance();
        /**
        * Initializes actual billboard set object and loads data from temporary holder(s) into it
        */
		virtual bool      load();
        /**
        * Unloades actual billboard set object and destroys it
        * @return
        */
		virtual bool      unLoad();
        /** @copydoc CBaseEditor::processParameters(Ogre::NameValuePairList &) */
		virtual void      processParameters(Ogre::NameValuePairList &params);
        /** @copydoc CBaseEditor::setupPropertiesWnd(bool) */
		virtual bool	  setupPropertiesWnd(bool present);
        /** @copydoc CBaseEditor::getObjectProperties(Ogre::NameValuePairList &) */
		virtual void      getObjectProperties(Ogre::NameValuePairList &retList);
        /** @copydoc CBaseEditor::handleCustomFunction(int, Ogre::String) */
		virtual bool      handleCustomFunction(int BIND_ID, Ogre::String val);
		/** @copydoc CBaseEditor::restore(Ogre::NameValuePairList &) */
		virtual void      restore(Ogre::NameValuePairList &retList);
		/** @copydoc CBaseEditor::getHandle() */
		inline virtual void    *getHandle() {return static_cast<void*>(m_BillboardSetHandle);};
        /**
        * Fetches axis aligned bounding box for while billboard set
        * @return axis aligned bounding box for while billboard set
        */
		virtual Ogre::AxisAlignedBox getAABB() {if(m_BillboardSetHandle) return m_BillboardSetHandle->getBoundingBox(); else return Ogre::AxisAlignedBox::BOX_NULL;};
        
        /**
        * Fetches billboard type as a string
        * @return billboard type as a string
        */
		virtual Ogre::String	getBillboardTypeString();
        /**
        * Fetches billboard origin as a string
        * @return billboard origin as a string
        */
		virtual Ogre::String	getBillboardOriginString();
        /**
        * Fetches billboard rotation as a string
        * @return billboard rotation as a string
        */
		virtual Ogre::String	getBillboardRotationString();

        /** @copydoc CBaseEditor::onDropMaterial(Ogre::Vector3, const Ogre::String&) */
        virtual void            onDropMaterial(Ogre::Vector3 position, const Ogre::String& materialname);
		/** @copydoc CBaseEditor::getPropertyContextMenu(unsigned int, UTFStringVector &) */
		virtual bool  getPropertyContextMenu(unsigned int itemid, UTFStringVector &menuitems);
		/** @copydoc CBaseEditor::onPropertyContextMenu(unsigned int, int) */
		virtual void  onPropertyContextMenu(unsigned int itemid, int menuresult);
        /**
        * Fetches data from temporary billboard(s) into actual billboard(s)
        * @param index billboard index (destination/source index)
        * @param data temporary billboard (source)
        * @param bAddAsNew flag signifying that temporary billboard data will be inserted into new actual billboard, not replacing existing actual billboard
        */
		virtual void setBillboardData(unsigned int index, BILLBOARD& data, const bool& bAddAsNew = false);
        /**
        * Fetches temporary billboard data
        * @return index temporary billboard index
        */
		virtual BILLBOARD& getBillboardData(unsigned int index);
        /**
        * Creates actual billboards using temporary billboards
        */
		virtual void popBillboards();
        /**
        * Places all data from actual billboard(s) into temporary billboard(s) storage
        */
		virtual void pushBillboards();

	protected:
		Ogre::BillboardSet	*m_BillboardSetHandle;          /** Actual billboard set handle */
		int					m_iBillboardType;               /** Billboard set type (wrapper) */
		bool				m_bSorting;                     /** Billboard set sorting type (wrapper) */
		int					m_iBillboardOrigin;             /** Billboard set origin type (wrapper) */
		int					m_iBillboardRotation;           /** Billboard set rotation type (wrapper) */
		Ogre::Real			m_DefaultWidth;                 /** Billboard set default width (wrapper) */
		Ogre::Real			m_DefaultHeight;                /** Billboard set default height (wrapper) */
		Ogre::String		m_Material;                     /** Billboard set default material name (wrapper) */
		bool				m_bPointRendering;              /** Billboard set default point rendering flag (wrapper) */
		Ogre::Real			m_RenderingDistance;            /** Billboard set default rendering distance (wrapper) */
		std::vector<BILLBOARD>   m_Billboards;              /** Temporary billboard(s) storage */

        /** 
        * Constructor 
        */
		CBillboardSetEditor();
        /** 
        * Destructor
        */
		virtual           ~CBillboardSetEditor();
        
        /**
        * Fetches billboard type from a billboard type string
        * @param value billboard type string
        * @return billboard type
        */
		Ogre::BillboardType         _convertBillboardType(const Ogre::String& value );
        /**
        * Fetches billboard sorting type from a billboard sorting type string
        * @param value billboard sorting type string
        * @return billboard sorting type
        */
		Ogre::SortMode              _convertSortingType(const Ogre::String& value );
        /**
        * Fetches billboard origin type from a billboard origin type string
        * @param value billboard origin type string
        * @return billboard origin type
        */
		Ogre::BillboardOrigin       _convertBillboardOriginType(const Ogre::String& value );
        /**
        * Fetches billboard rotation type from a billboard rotation type string
        * @param value billboard rotation type string
        * @return billboard rotation type
        */
		Ogre::BillboardRotationType _convertBillboardRotationType(const Ogre::String& value );
	};

    //! Billboard set editor factory class
    /*!  
        A class that instantiates billboard set editor and tracks it thereafter
    */
	class OgitorExport CBillboardSetEditorFactory: public CBaseEditorFactory
	{
	public:
        /**
        * Constructor
        */
		CBillboardSetEditorFactory();
        /**
        * Destructor
        */
		virtual ~CBillboardSetEditorFactory() {};
        /** @copydoc CBaseEditorFactory::Init() */
		virtual void Init();
        /** @copydoc CBaseEditorFactory::CreateObject(CBaseEditor **, Ogre::NameValuePairList &) */
		virtual CBaseEditor *CreateObject(CBaseEditor **parent, Ogre::NameValuePairList &params);
        /** @copydoc CBaseEditorFactory::GetPlaceHolderName() */
		virtual Ogre::String GetPlaceHolderName() {return "scbLight_Omni.mesh";};
	};
}
